const md5 = require('md5');
const fs = require('fs');
const qs = require('qs');
const config = require('../config/config');
const httpResponse = require('../modal/response');

class BundleController {
    constructor(ctx) {
        this.ctx = ctx;
    }

    async list() {
        const { request, response } = this.ctx;

        const query = qs.parse(request.querystring);
        const projectId = query.projectId;
        let res;

        if (projectId) {
            const projectInfo = res = await this.ctx.db.execute(`select * from project where unlink = 0 and id = ${projectId}`);
            if (projectInfo.length === 0) {
                return httpResponse.badRequest(response, 'project is not exist.');
            }

            res = await this.ctx.db.execute(`select * from file where unlink = 0 and projectId = ${projectId} order by id desc limit 20`);
            for (const project of res[0]) {
                project.project = projectInfo[0];
            }
        } else
            res = await this.ctx.db.execute('select * from file where unlink = 0 order by id desc limit 20');

        return httpResponse.ok(response, res[0]);
    }

    async upload() {
        const { request, response } = this.ctx;

        const dir = config.storage.root;
        const body = request.body;

        const query = qs.parse(request.querystring);
        const projectId = query.projectId;
        const name = query.name;

        if (!projectId) {
            this.ctx.status = 400;
            return response.body = 'project is required';
        }

        const [projectRows] = await this.ctx.db.execute(`select * from project where id = ${projectId}`);

        if (projectRows.length === 0) {
            this.ctx.status = 400;
            return response.body = 'project is not exist';
        }

        const fileMd5 = md5(body);
        const timestamp = parseInt(new Date().getTime() / 1000);
        const fileName = name ? `${timestamp}.${name}` : `bundle.${fileMd5}.${timestamp}`;
        const saveName = `${config.storage.root}/${fileName}`;
        const url = `${config.server.host}/files/${fileName}`;

        const size = request.headers['content-length'] || -1;

        // console.log(config.server.host);

        const stat = fs.existsSync(dir) && fs.lstatSync(dir).isDirectory();

        if (!stat) {
            fs.mkdirSync(dir);
        }

        const writer = fs.createWriteStream(saveName);

        const success = await new Promise(resolve => {
            // console.log(body);
            const buffer = Buffer.from(body);
            writer.write(buffer, () => {
                resolve(1);
            });
        });

        const [fileRows] = await this.ctx.db.execute("insert into file(name, path, md5, tag,ctime,unlink,projectID,size) values(?,?,?,'javascript',now(), 0, ?, ?)", [fileName, url, fileMd5, projectId, size]);

        if (success === 1 && fileRows.insertId) {
            const res = {
                status: 'done',
                data: {
                    id: fileRows.insertId,
                    fileName: name ? name : fileName,
                    saveName: saveName,
                    url: url,
                    fileMd5: fileMd5,
                    timestamp: timestamp,
                    size: size,
                    project: projectRows[0]
                }
            };

            response.body = JSON.stringify(res);

            if (this.ctx.ws) {
                this.ctx.ws.to('publish').emit('message', response.body);
            }

        } else {
            this.ctx.status = 500;
            response.body = 'upload error';
        }
    }

    async delete() {
        const { request, response } = this.ctx;

        const query = qs.parse(request.querystring);
        const bundleId = query.id;

        if (!bundleId) {
            return httpResponse.badRequest(response, 'bundle id is required');
        }

        const [bundleRows] = await this.ctx.db.execute(`select * from file where id = ${bundleId}`);

        if (bundleRows.length === 0) {
            return httpResponse.badRequest(response, 'bundle is not exist');
        }

        try {
            const [updateRows] = await this.ctx.db.execute(`update file set unlink = 1 where id = ${bundleId}`);
            return httpResponse.ok(response, updateRows);
        } catch (error) {
            return httpResponse.internalError(response, String(error));
        }
    }
}

module.exports = BundleController;
